/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.material.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;


import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.springblade.common.enums.library.QuestionType;
import org.springblade.common.exception.TrainingServiceException;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.library.entity.QuestionBankEntity;
import org.springblade.modules.library.entity.QuestionOptionEntity;
import org.springblade.modules.library.service.IQuestionBankService;
import org.springblade.modules.library.service.IQuestionOptionService;
import org.springblade.modules.library.vo.QuestionOptionVO;
import org.springblade.modules.material.entity.*;
import org.springblade.modules.material.service.*;
import org.springblade.modules.material.vo.*;
import org.springblade.modules.material.wrapper.AnswerWrapper;
import org.springblade.modules.material.wrapper.PaperReleaseWrapper;
import org.springblade.modules.personal.entity.UserBaseEntity;
import org.springblade.modules.personal.service.IUserBaseService;
import org.springframework.web.bind.annotation.*;
import org.springblade.core.boot.ctrl.BladeController;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 答题表 控制器
 *
 * @author BladeX
 * @since 2023-04-03
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-answer/answer")
@Api(value = "答题表", tags = "答题表接口")
public class AnswerController extends BladeController {

	private final IAnswerService answerService;
	private final IAnswerOptionService answerOptionService;
	private final IUserBaseService userBaseService;
	private final IPaperService paperService;
	private final IPaperReleaseService paperReleaseService;
	private final IQuestionBankService questionBankService;
	private final IQuestionOptionService questionOptionService;

	/**
	 * 答题表 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入answer")
	public R<PaperAnswerVO> detail(PaperAnswerEntity answer) {
		PaperAnswerEntity detail = answerService.getOne(Condition.getQueryWrapper(answer));
		return R.data(AnswerWrapper.build().entityVO(detail));
	}

	/**
	 * 答题表 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入answer")
	public R<IPage<PaperAnswerVO>> list(PaperAnswerEntity answer, Query query) {
		IPage<PaperAnswerEntity> pages = answerService.page(Condition.getPage(query), Condition.getQueryWrapper(answer));
		return R.data(AnswerWrapper.build().pageVO(pages));
	}

	/**
	 * 答题表 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入answer")
	public R save(@Valid @RequestBody PaperAnswerEntity answer) {
		return R.status(answerService.save(answer));
	}

	/**
	 * 答题表 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入answer")
	public R update(@Valid @RequestBody PaperAnswerEntity answer) {
		return R.status(answerService.updateById(answer));
	}

	/**
	 * 答题表 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(answerService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 成绩分页列表 自定义分页
	 */
	@GetMapping("/score-list")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "获取成绩表分页列表", notes = "传入answer")
	public R<IPage<PaperAnswerVO>> scoreList(PaperAnswerVO answer, Query query) {
		IPage<PaperAnswerVO> pages = answerService.selectAnswerScorePage(Condition.getPage(query), answer);
		return R.data(pages);
	}


	/**
	 * 导出数据
	 */
	@GetMapping("/export-answer-detail")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "获取用户作答试卷数据", notes = "传入试卷id")
	public R exportClassesUser(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, HttpServletResponse response) {
		List<PaperReleaseVO> resultAnswerPaper = new ArrayList<>();

		List<PaperAnswerEntity> answerList = answerService.listByIds(Func.toLongList(ids));
		answerList.forEach(answer -> {
			PaperReleaseEntity paperReleaseEntity = paperReleaseService.getById(answer.getPaperReleaseId());
			PaperReleaseVO paperReleaseVO = new PaperReleaseVO();


			if (null == paperReleaseEntity.getIsRule() || 0 == paperReleaseEntity.getIsRule()) {//非规则组卷
				//1.获取试卷
				paperReleaseVO = paperReleaseService.getExamPaper(answer.getPaperReleaseId());
				if (null == paperReleaseVO) throw new TrainingServiceException("试卷不存在");
				paperReleaseVO.setPaperReleaseDetailList(paperService.dealQuestionByQUestionType(paperReleaseVO.getPaperReleaseDetailList()));
				//2.查询该用户的所有作答选项
				List<Long> checkOptionIds = answerOptionService.list(Wrappers.<PaperAnswerOptionEntity>query().lambda()
					.eq(PaperAnswerOptionEntity::getAnswerId, answer.getId())).stream().map(PaperAnswerOptionEntity::getChecked).collect(Collectors.toList());

				paperReleaseVO.getPaperReleaseDetailList().forEach(releaseDetail -> {
					if (QuestionType.SHORT.getCode() != releaseDetail.getQuestionType().intValue()
						&& QuestionType.FILL.getCode() != releaseDetail.getQuestionType().intValue()) {//如果不是简答题或填空题

						releaseDetail.getQuestionOptionList().forEach(option -> {
							if (checkOptionIds.contains(option.getId())) option.setChoice(1);
							else option.setChoice(0);
						});

					} else {//简答题、填空题处理
						releaseDetail.getQuestionOptionList().forEach(option -> {

							PaperAnswerOptionEntity shortAnswer = answerOptionService.getOne(Wrappers.<PaperAnswerOptionEntity>query().lambda()
								.eq(PaperAnswerOptionEntity::getAnswerId, answer.getId())
								.eq(PaperAnswerOptionEntity::getReleaseDetailId, releaseDetail.getId()));
							option.setAnswerContent(shortAnswer.getAnswerContent());
						});
					}
				});

			} else {//规则组卷
				paperReleaseVO = PaperReleaseWrapper.build().entityVO(paperReleaseEntity);

				//1.获取该人员的作答题目集
				List<PaperAnswerOptionEntity> answerOptionEntityList = answerOptionService.list(Wrappers.<PaperAnswerOptionEntity>query().lambda()
					.eq(PaperAnswerOptionEntity::getUserId, AuthUtil.getUserId())
					.eq(PaperAnswerOptionEntity::getAnswerId, answer.getId()));
				if (CollectionUtil.isNotEmpty(answerOptionEntityList)) {
					//去重
					List<Long> questionIds = answerOptionEntityList.stream().map(PaperAnswerOptionEntity::getQuestionId).distinct().collect(Collectors.toList());

					//查询对应的题目
					List<QuestionBankEntity> queryList = questionBankService.listByIds(questionIds);

					//2.查询该用户的所有作答选项
					List<Long> checkOptionIds = answerOptionEntityList.stream().map(PaperAnswerOptionEntity::getChecked).collect(Collectors.toList());

					//将试题转换成paperReleaseDetail
					List<PaperReleaseDetailVO> releaseDetailVOList = queryList.stream().map(queryVo -> {
						PaperReleaseDetailVO paperReleaseDetailVO = new PaperReleaseDetailVO();
						paperReleaseDetailVO.setContent(queryVo.getContent());
						paperReleaseDetailVO.setQuestionType(queryVo.getQuestionType());
						paperReleaseDetailVO.setDifficultyLevel(queryVo.getDifficultyLevel());
						paperReleaseDetailVO.setQuestionId(queryVo.getId());
						paperReleaseDetailVO.setReleaseId(answer.getPaperReleaseId());
						paperReleaseDetailVO.setValue(getValueByQuestionType(queryVo.getQuestionType(), paperReleaseEntity));

						//附上选项
						if (QuestionType.SHORT.getCode().intValue() == queryVo.getQuestionType()) { //如果是简答题
							List<QuestionOptionVO> questionOptionList = new ArrayList<>();
							QuestionOptionVO questionOptionVO = new QuestionOptionVO();
							questionOptionVO.setQuestionId(queryVo.getId());
							PaperAnswerOptionEntity shortAnswer = answerOptionService.getOne(Wrappers.<PaperAnswerOptionEntity>query().lambda()
								.eq(PaperAnswerOptionEntity::getAnswerId, answer.getId())
								.eq(PaperAnswerOptionEntity::getQuestionId, queryVo.getId()));

							questionOptionVO.setAnswerContent(shortAnswer.getAnswerContent());
							questionOptionList.add(questionOptionVO);
							paperReleaseDetailVO.setQuestionOptionList(questionOptionList);
						} else {
							paperReleaseDetailVO.setQuestionOptionList(
								//将questionOption转成questionOptionVO
								questionOptionService.list(Wrappers.<QuestionOptionEntity>query()
									.lambda().eq(QuestionOptionEntity::getQuestionBankId, queryVo.getId())).stream().map(questionOption -> {
									QuestionOptionVO questionOptionVO = new QuestionOptionVO();
									BeanUtil.copyProperties(questionOption, questionOptionVO);
									if (checkOptionIds.contains(questionOptionVO.getId()))
										questionOptionVO.setChoice(1);
									else questionOptionVO.setChoice(0);
									return questionOptionVO;
								}).collect(Collectors.toList())
							);
						}

						return paperReleaseDetailVO;
					}).collect(Collectors.toList());
					paperReleaseVO.setPaperReleaseDetailList(releaseDetailVOList);
				}
			}

			UserBaseEntity userBaseEntity = userBaseService.getOne(Wrappers.<UserBaseEntity>query().lambda().eq(UserBaseEntity::getUserId, answer.getUserId()));
			if (null != userBaseEntity) {
				paperReleaseVO.setUserName(userBaseEntity.getUserName());
				paperReleaseVO.setIdCard(userBaseEntity.getIdCard());
				paperReleaseVO.setUserId(answer.getUserId());
			}
			paperReleaseVO.setScore(answer.getScore());
			resultAnswerPaper.add(paperReleaseVO);

		});
		return R.data(resultAnswerPaper);
	}


	//根据题目类型获取试题分数
	public Integer getValueByQuestionType(int questionType, PaperReleaseEntity paperReleaseEntity) {
		Integer value = 0;
		switch (questionType) {
			case 1:
				value = paperReleaseEntity.getSingleScore();
				break;
			case 2:
				value = paperReleaseEntity.getMultipleScore();
				break;
			case 3:
				value = paperReleaseEntity.getJudgeScore();
				break;
			case 4:
				value = paperReleaseEntity.getFillScore();
				break;
			case 5:
				value = paperReleaseEntity.getShortScore();
				break;
		}
		return value;
	}
}
